/**

 * Example of Android PhoneGap Plugin

 */

package com.cirpho;

import java.io.*;
import org.json.JSONArray;

import org.json.JSONException;
import org.json.JSONObject;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.util.Log;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import com.phonegap.api.PluginResult.Status;
import org.apache.commons.codec.binary.Base64;

public class CirphoCameraPlugin extends Plugin {

	/** List Action */

	public static final String ACTION = "camera";

	public static final int MEDIA_TYPE_IMAGE = 1;
	public static final int MEDIA_TYPE_VIDEO = 2;
	public static final String TAG = "";

	private int mQuality = 50; // Compression quality hint (0-100: 0=low quality &
							// high compression, 100=compress of max quality)
	private int targetWidth; // desired width of the image
	private int targetHeight; // desired height of the image
	private Uri imageUri; // Uri of captured image
	private int x; // Type of encoding to use
	private int y; // What type of media to retrieve
	private int imageHeight;
	private int imageWidth;
	private String imageUriString;
	public String callbackId;

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.phonegap.api.Plugin#execute(java.lang.String,
	 * 
	 * org.json.JSONArray, java.lang.String)
	 */
	@Override
	public PluginResult execute(String action, JSONArray args, String callbackId) {
		Log.d("CirphoCameraPlugin", "Plugin Called");
		PluginResult result = null;
		PluginResult resultTemp = null;
		try {
			if (ACTION.equals(action)) {
				this.targetHeight = 0;
				this.targetWidth = 0;

				JSONObject options = args.optJSONObject(0);
				Log.d("CirphoCameraPlugin",
						"imageUri " + options.getString("imageUri"));
				if (options != null) {
					this.imageUriString = options.getString("imageUri");
					this.imageUriString = this.getRealPathFromURI(Uri.parse(this.imageUriString));
					this.imageUri = Uri.fromFile(new File(this.imageUriString));
					if(options.getString("x") == null){
						this.x = 0;
					}else{
						this.x = Integer.parseInt(options.getString("x"));
					}
					if(options.getString("y") == null){
						this.y = 0;
					}else{
						this.y = Integer.parseInt(options.getString("y"));
					}
					
					this.targetHeight = Integer.parseInt(options.getString("targetHeight"));
					this.targetWidth = Integer.parseInt(options.getString("targetWidth"));
					this.imageHeight = options.getInt("imageHeight");
					this.imageWidth = options.getInt("imageWidth");
				}
				
				try {
					
					Bitmap bitmap;
					bitmap = android.provider.MediaStore.Images.Media
							.getBitmap(this.ctx.getContentResolver(), this.imageUri);
					int bitMapHeight = bitmap.getHeight();
					int bitMapWidth = bitmap.getWidth();
					
					
					int rate = bitMapHeight *100 / this.imageHeight;
					int rateWidth = bitMapWidth *100 / this.imageWidth;
					
					this.x = this.x * rateWidth/100;
					this.y = this.y * rate/100;
					this.targetWidth = this.targetWidth * rateWidth/100;
					this.targetHeight = this.targetHeight * rate/100;
					
					if(this.targetWidth > bitMapWidth || this.targetWidth == 0 ){
						this.targetWidth = bitMapWidth - this.x;
					}
					if(this.targetHeight > bitMapHeight || this.targetHeight == 0){
						this.targetHeight = bitMapHeight - this.y;
					}
					
					Log.d("CirphoCameraPlugin",
							"rateWidth " + rateWidth);
					Log.d("CirphoCameraPlugin",
							"rate " + rate);
					Log.d("CirphoCameraPlugin",
							"bitMapHeight " + bitMapHeight);
					Log.d("CirphoCameraPlugin",
							"bitMapHeight " + bitMapWidth);
					Log.d("CirphoCameraPlugin",
							"targetHeight " + this.targetHeight);
					
					bitmap = Bitmap.createBitmap(bitmap, this.x, this.y, this.targetWidth, this.targetHeight);
					
					ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
			        try {
			            if (bitmap.compress(CompressFormat.JPEG, mQuality, jpeg_data)) {
			                byte[] code = jpeg_data.toByteArray();
			                byte[] output = Base64.encodeBase64(code);
			                String js_out = new String(output);
			                resultTemp = new PluginResult(PluginResult.Status.OK, js_out);
			                js_out = null;
			                output = null;
			                code = null;
			            }
			        }
			        catch(Exception e) {
			            this.failPicture("Error compressing image.");
			        }
			        jpeg_data = null;
					
					
					//result = new PluginResult(Status.OK, this.imageUriString);
			        result = resultTemp;
					//result = new PluginResult(Status.OK, true);
				} catch (Exception jsonEx) {
					Log.d("CirphoCameraPlugin",
							"Got JSON Exception " + jsonEx.getMessage());
					result = new PluginResult(Status.JSON_EXCEPTION);
				}
			} else {
				result = new PluginResult(Status.INVALID_ACTION);
				Log.d("CirphoCameraPlugin", "Invalid action : " + action
						+ " passed");
			}
		//} catch (JSONException e) {
		} catch (Exception e) {
			e.printStackTrace();
			return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
		}
		return result;
	}

	/**
	 * Scales the bitmap according to the requested size.
	 * 
	 * @param bitmap
	 *            The bitmap to scale.
	 * @return Bitmap A new Bitmap object of the same bitmap after scaling.
	 */
	public Bitmap scaleBitmap(Bitmap bitmap) {
		int newWidth = this.targetWidth;
		int newHeight = this.targetHeight;
		int origWidth = bitmap.getWidth();
		int origHeight = bitmap.getHeight();

		// If no new width or height were specified return the original bitmap
		if (newWidth <= 0 && newHeight <= 0) {
			return bitmap;
		}
		// Only the width was specified
		else if (newWidth > 0 && newHeight <= 0) {
			newHeight = (newWidth * origHeight) / origWidth;
		}
		// only the height was specified
		else if (newWidth <= 0 && newHeight > 0) {
			newWidth = (newHeight * origWidth) / origHeight;
		}
		// If the user specified both a positive width and height
		// (potentially different aspect ratio) then the width or height is
		// scaled so that the image fits while maintaining aspect ratio.
		// Alternatively, the specified width and height could have been
		// kept and Bitmap.SCALE_TO_FIT specified when scaling, but this
		// would result in whitespace in the new image.
		else {
			double newRatio = newWidth / (double) newHeight;
			double origRatio = origWidth / (double) origHeight;

			if (origRatio > newRatio) {
				newHeight = (newWidth * origHeight) / origWidth;
			} else if (origRatio < newRatio) {
				newWidth = (newHeight * origWidth) / origHeight;
			}
		}

		return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
	}
	public String getRealPathFromURI(Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = this.ctx.getContentResolver().query(contentUri, proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

	/**
	 * Compress bitmap using jpeg, convert to Base64 encoded string, and return
	 * to JavaScript.
	 * 
	 * @param bitmap
	 */
	public void processPicture(Bitmap bitmap) {
		ByteArrayOutputStream jpeg_data = new ByteArrayOutputStream();
		try {
			if (bitmap.compress(CompressFormat.JPEG, mQuality, jpeg_data)) {
				byte[] code = jpeg_data.toByteArray();
				byte[] output = Base64.encodeBase64(code);
				String js_out = new String(output);
				this.success(new PluginResult(PluginResult.Status.OK, js_out),
						this.callbackId);
				js_out = null;
				output = null;
				code = null;
			}
		} catch (Exception e) {
			this.failPicture("Error compressing image.");
		}
		jpeg_data = null;
	}

	/**
	 * Send error message to JavaScript.
	 * 
	 * @param err
	 */
	public void failPicture(String err) {
		this.error(new PluginResult(PluginResult.Status.ERROR, err),
				this.callbackId);
	}

}